package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.dto.SetmealDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.Setmeal;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.SetmealDishService;
import com.itheima.reggie.service.SetmealService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.ietf.jgss.Oid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import javax.websocket.server.PathParam;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@Slf4j
@RequestMapping("/setmeal")
@Api(tags = "套餐相关接口")
public class SetmealController {
    @Autowired
    private SetmealService setmealService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SetmealDishService setmealDishService;


    /**
     * 分页查询
     *
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("套餐分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", required = true),
            @ApiImplicitParam(name = "pageSize", value = "单页记录数", required = true),
            @ApiImplicitParam(name = "name", value = "姓名", required = false)
    })
    public R<Page> page(int page, int pageSize, String name) {

        Page<Setmeal> setmealPage = new Page<>(page, pageSize);
        //造一个空的传递类
        Page<SetmealDto> setmealDtoPage = new Page<>();
        //先把基本信息查出来
        QueryWrapper<Setmeal> setmealQueryWrapper = new QueryWrapper<>();
        setmealQueryWrapper.lambda().orderByDesc(Setmeal::getUpdateTime);
        setmealQueryWrapper.lambda().like(null != name, Setmeal::getName, name);
        setmealService.page(setmealPage, setmealQueryWrapper);
        //把setmealPage的信息传递到setmealDtoPage上,把要补充的信息补上
        //1.套餐关联的菜品集合
        //2.套餐的类型/分类名称
        BeanUtils.copyProperties(setmealPage, setmealDtoPage);
        List<Setmeal> records = setmealPage.getRecords();//setmeals
        List<SetmealDto> list = records.stream().map(
                new Function<Setmeal, SetmealDto>() {
                    @Override
                    public SetmealDto apply(Setmeal setmeal) {
                        SetmealDto setmealDto = new SetmealDto();
                        BeanUtils.copyProperties(setmeal, setmealDto);
                        Long categoryId = setmeal.getCategoryId();
                        Category category = categoryService.getById(categoryId);
                        if (null != category) {
                            String categoryName = category.getName();
                            setmealDto.setCategoryName(categoryName);
                        }
                        return setmealDto;
                    }
                }).collect(Collectors.toList());
        setmealDtoPage.setRecords(list);
        return R.success(setmealDtoPage);
    }

    /**
     * 增加新的套餐
     *
     * @param setmealDto
     * @return
     */
    /*
     * 保存新添加的套餐
     * */
    @PostMapping
    @CacheEvict(value = "setmealCache", beforeInvocation = false) //清除setmealCache名称下,所有的缓存数据
    public R<String> save(@RequestBody SetmealDto setmealDto) {
        setmealService.saveWithDish(setmealDto);
        return R.success("保存成功了鉄子!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    //1.删除之前要判断是不是停售的状态,如果是再删除
    //1.1 先用ids获取套餐对象
    //1.2 用套餐对象获取套餐的状态
    //1.3 判断后进行删除操作
    //2.删除是逻辑删除
    //3.要把套餐里面的菜品一并删除
    // allEntries = true 把redis中所有的缓存都删除
    @DeleteMapping()
    @CacheEvict(value = "setmealCache",allEntries = true) //清除setmealCache名称下,所有的缓存数据
    public R<String> delete(@RequestParam List<Long> ids) {
        for (Long id : ids) {
            if (0 != setmealService.getById(id).getStatus()) {
                return R.error("停售状态才能删除");
            }
        }
        setmealService.removeWithSetmealDishs(ids);
        return R.success("删除成功了鉄子");
    }

    /**
     * //通过前端获得的套餐的id获取套餐的所有属性并返回/回显
     *
     * @param id
     * @return
     */

    @GetMapping("/{id}")
    public R<SetmealDto> getById(@PathVariable Long id) {//套餐的id
        SetmealDto setmealDto = new SetmealDto();
        Setmeal setmeal = setmealService.getById(id);//获取对应的套餐
        BeanUtils.copyProperties(setmeal, setmealDto);//把套餐的属性拷贝到传递对象中
        Long categoryId = setmeal.getCategoryId();//获取套餐类型的id
        Category category = categoryService.getById(categoryId);//获取套餐类型
        //设置categoryname
        String categoryName = category.getName();
        setmealDto.setCategoryName(categoryName);
        //设置setmealDishes
        //获取套餐下的所有菜品
        //菜品的套餐id属性和套餐的id属性一样
        QueryWrapper<SetmealDish> setmealDishQueryWrapper = new QueryWrapper<>();
        setmealDishQueryWrapper.lambda().eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> list = setmealDishService.list(setmealDishQueryWrapper);//获取套餐下的菜品
        setmealDto.setSetmealDishes(list);
        return R.success(setmealDto);
    }

    //按照套餐的分类id和状态获取套餐下的菜品并返回
    //我要得到的是套餐和套餐下面的菜品集合
    //我从前端得到的数据是:分类的id 套餐状态
    @GetMapping("/list")
    @Cacheable(value = "setmealCache", key = "#categoryId + '-' + #status")
    public R<List<SetmealDto>> getByIdAndStatus(@RequestParam Long categoryId, @RequestParam Integer status) {
        QueryWrapper<Setmeal> setmealDtoQueryWrapper = new QueryWrapper<>();
        setmealDtoQueryWrapper.lambda().eq(null != categoryId, Setmeal::getCategoryId, categoryId);
        setmealDtoQueryWrapper.lambda().eq(null != status, Setmeal::getStatus, status);
        List<Setmeal> setmeals = setmealService.list(setmealDtoQueryWrapper);
        //找到对应的套餐后把套餐下的菜品也找到 加到dto对象中
        if (null != setmeals) {
            //从套餐集合中挨个取
            //取到其中的一个套餐,新建一个setmealdto对象,把setmeal的东西都拷里头
            //取的这个套餐下所有菜品的信息 然后把信息也都拷里头 返回一个setmealdto的集合
            List<SetmealDto> setmealDtos = setmeals.stream().map(new Function<Setmeal, SetmealDto>() {
                @Override
                public SetmealDto apply(Setmeal item) {
                    SetmealDto setmealDto = new SetmealDto();
                    BeanUtils.copyProperties(item, setmealDto);
                    Long id = item.getId();
                    QueryWrapper<SetmealDish> setmealDishQueryWrapper = new QueryWrapper<>();
                    //判断:套餐的id和菜品的套餐id属性一致
                    setmealDishQueryWrapper.lambda().eq(id != null, SetmealDish::getSetmealId, id);
                    List<SetmealDish> setmealDishes = setmealDishService.list(setmealDishQueryWrapper);
                    setmealDto.setSetmealDishes(setmealDishes);
                    return setmealDto;
                }
            }).collect(Collectors.toList());

            return R.success(setmealDtos);
        }
        return R.error("此套餐下菜品为空");
    }


    /**
     * 修改套餐
     *
     * @param setmealDto
     * @return
     */
    //保存修改
    @PutMapping
    public R<String> update(@RequestBody SetmealDto setmealDto) {

        log.info("修改setmealDto :" + setmealDto.toString());

        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDto, setmeal, "setmealDishes", "categoryName");
        setmealService.updateById(setmeal);
        log.info("修改setmeal :" + setmeal.toString());

        //获取套餐的id
        Long id = setmeal.getId();
        //根据套餐的id删除套餐内菜品
        QueryWrapper<SetmealDish> setmealDishQueryWrapper = new QueryWrapper<>();
        setmealDishQueryWrapper.lambda().in(null != id, SetmealDish::getSetmealId, id);
        setmealDishService.remove(setmealDishQueryWrapper);

//目前可以删除了 但是添加不了
//因为我从前端得到的所有菜品没有 id!

        List<SetmealDish> list = setmealDto.getSetmealDishes();//前端传来的修改后的菜品
        list.stream().forEach(new Consumer<SetmealDish>() {
            @Override
            public void accept(SetmealDish setmealDish) {
                setmealDish.setSetmealId(id);
            }
        });
        setmealDishService.saveBatch(list);

        return R.success("修改成功了鉄子");
    }

    /**
     * 修改停售和起售状态
     *
     * @param status
     * @param ids
     * @return
     */

    @PostMapping("/status/{status}")
    public R<String> update(@PathVariable Integer status, @RequestParam List<Long> ids) {
        log.info("status : {}, ids : {}", status, ids);
//        for (Long id : ids) {
//            Setmeal setmeal = setmealService.getById(id);
//            setmeal.setStatus(status);
//            setmealService.updateById(setmeal);
//        }
        ids.forEach(id -> {
            Setmeal setmeal = setmealService.getById(id);
            setmeal.setStatus(status);
            setmealService.updateById(setmeal);
        });


        return R.success("修改成功了鉄子!");
    }

    /**
     * 前台的套餐信息回显
     *
     * @param id
     * @return
     */
    //根据套餐的id获得套餐的菜品和菜品口味所以返回的是setmealdto集合
//问题是前台不显示套餐内菜品的照片
    @GetMapping("/dish/{id}")
    public R<List<SetmealDish>> getSetmealDtosById(@PathVariable Long id) {
        //根据套餐的id获得套餐菜品集合的对象
        QueryWrapper<SetmealDish> setmealQueryWrapper = new QueryWrapper<>();
        setmealQueryWrapper.lambda().eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> setmealDishes = setmealDishService.list(setmealQueryWrapper);

        if (setmealDishes != null) {
            //把套餐内菜品的照片名称设置进去
            //就是把套餐关联的菜品集合和分类的名称加进去
//            List<SetmealDto> setmealDtos = setmealDishes.stream().map(new Function<SetmealDish, SetmealDto>() {
//                @Override
//                public SetmealDto apply(SetmealDish setmealDish) {
//                    SetmealDto setmealDto = new SetmealDto();
//                    BeanUtils.copyProperties(setmealDish,setmealDto);
//                    QueryWrapper<Dish> dishQueryWrapper = new QueryWrapper<>();
//                    return setmealDto;
//                }
//            }).collect(Collectors.toList());
            return R.success(setmealDishes);

        }


        //根据套餐的对象获取套餐下的菜品
        return R.error("此套餐下无菜品");
    }


}
